package ar.edu.caece.compiler.grammar.factories;

import ar.edu.caece.compiler.grammar.AbstractTokenVisitorFactory;
import ar.edu.caece.compiler.grammar.Recognizer;
import ar.edu.caece.compiler.grammar.TokenRecognizer;
import ar.edu.caece.compiler.grammar.TokenVisitor;
import ar.edu.caece.compiler.grammar.attributes.Attribute;
import ar.edu.caece.compiler.grammar.attributes.tree.NodeBloque;
import ar.edu.caece.compiler.grammar.attributes.tree.NodeSentencia;
import ar.edu.caece.compiler.grammar.nonterminals.LISTAPROP;
import ar.edu.caece.compiler.grammar.nonterminals.LISTAPROP1;
import ar.edu.caece.compiler.grammar.nonterminals.PROP;


public class LISTAPROP1Factory extends AbstractTokenVisitorFactory {

	private static LISTAPROP1Factory INSTANCE;
	
	public static LISTAPROP1Factory getInstance() throws Exception {
		if(INSTANCE==null) INSTANCE = new LISTAPROP1Factory();
		return INSTANCE;
	}
	
	private PROPFactory propFactory;
	private LISTAPROPFactory listapropFactory;
	private TokenVisitor parsePROP;
	private TokenVisitor parseLISTAPROP;
	
	private Initializer initializer = new Initializer() {
		
		@Override
		public void init() throws Exception {
			initializer = NoOperationInitializer.getInstance();
			propFactory = PROPFactory.getInstance();
			listapropFactory = LISTAPROPFactory.getInstance();
			parseLISTAPROP = listapropFactory.makeVisitor();
			parsePROP = propFactory.makeVisitor();
		}
	};
	
	private LISTAPROP1Factory() throws Exception {

	}
	
	@Override
	public TokenVisitor makeChainedVisitor(
			final TokenVisitor siguiente) throws Exception {
		initializer.init();

		return new TokenVisitor() {

			@Override
			public Recognizer defaultCase(TokenRecognizer llamador)
					throws Exception {
				NodeBloque bloque = new NodeBloque((NodeBloque) getAttribute(Attribute.ARBOL_HEREDADO));

				TokenVisitor parsePROP2 = propFactory.makeChainedVisitor(siguiente);
				parsePROP2.addInheretedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,getAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA));
				parsePROP2.addInheretedAttribute(Attribute.ARBOL_HEREDADO,getAttribute(Attribute.ARBOL_HEREDADO));
				Recognizer result = llamador.execute(parsePROP2);
				if(result instanceof PROP) {
					parsePROP.addInheretedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,getAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA));
					parseLISTAPROP.addInheretedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,getAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA));

					PROP prop = (PROP) result;
					bloque.addSentencia((NodeSentencia) prop.getAttribute(Attribute.ARBOL_SINTETIZADO));
					parseLISTAPROP.addInheretedAttribute(Attribute.ARBOL_HEREDADO, bloque);
					LISTAPROP listaprop = (LISTAPROP) nextToken().execute(parseLISTAPROP);
					LISTAPROP1 listaprop1 = new LISTAPROP1 (prop, listaprop);
					listaprop1.addAttribute(Attribute.ARBOL_SINTETIZADO, listaprop.getAttribute(Attribute.ARBOL_SINTETIZADO));

					return listaprop1;
					} 
				else {
					return result;
				}
			}
			
		};
	
	}
	@Override
	public TokenVisitor makeVisitor() throws Exception {
		initializer.init();

		return new TokenVisitor() {

			@Override
			public Recognizer defaultCase(TokenRecognizer llamador) throws Exception {
				NodeBloque bloque = new NodeBloque((NodeBloque) getAttribute(Attribute.ARBOL_HEREDADO));

				parsePROP.addInheretedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,getAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA));
				parseLISTAPROP.addInheretedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,getAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA));

				PROP prop = (PROP) llamador.execute(parsePROP);
				bloque.addSentencia((NodeSentencia) prop.getAttribute(Attribute.ARBOL_SINTETIZADO));
				parseLISTAPROP.addInheretedAttribute(Attribute.ARBOL_HEREDADO, bloque);
				LISTAPROP listaprop = (LISTAPROP) nextToken().execute(parseLISTAPROP);
				LISTAPROP1 listaprop1 = new LISTAPROP1 (prop, listaprop);
				listaprop1.addAttribute(Attribute.ARBOL_SINTETIZADO, listaprop.getAttribute(Attribute.ARBOL_SINTETIZADO));
				return listaprop1;
			}
		};
	}
	
	
}
